package com.asiainfo.dacp.datastash.broker.facade.state;

import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.asiainfo.dacp.datastash.broker.core.BrokerException;
import com.asiainfo.dacp.datastash.broker.core.enums.ErrorCodeEnum;
import com.asiainfo.dacp.datastash.broker.core.enums.UnitStateEnum;
import com.asiainfo.dacp.datastash.broker.core.vo.StashUnit;
import com.asiainfo.dacp.datastash.orm.dao.log.DataStashUnitEventLogDao;
import com.asiainfo.dacp.datastash.orm.dao.state.DataStashUnitStateLogDao;
import com.asiainfo.dacp.datastash.orm.po.log.DataStashUnitEventLogPo;
import com.asiainfo.dacp.datastash.orm.po.state.DataStashUnitStateLogPo;
import com.asiainfo.dacp.util.BeanConvertUtils;
import com.google.common.base.Strings;

/**
 * 单元数据库状态操作
 * 
 * @author MeiKefu
 * @date 2017-11-30
 */
@Service
public class UnitStateLogService {

	@Autowired
	private DataStashUnitStateLogDao unitStateDao;

	@Autowired
	private DataStashUnitEventLogDao unitLogDao;

	public List<DataStashUnitStateLogPo> queryNonOverUnitState(String unitCode, String batchNo) {
		List<DataStashUnitStateLogPo> unitStatePo = unitStateDao.findUnitStateNonOver(unitCode, batchNo);
		return unitStatePo; 
	}

	/**
	 * 创建任务数据库支持久化
	 * 
	 * @param stashUnit
	 */
	@Transactional
	public void create(StashUnit stashUnit) {
		DataStashUnitStateLogPo unitStatePo = unitStateDao.findOne(stashUnit.getUnitProcId());
		if (unitStatePo == null) {
			unitStatePo = BeanConvertUtils.copyBean(stashUnit, DataStashUnitStateLogPo.class);
			unitStatePo.setMessage("初始化任务");
			unitStateDao.save(unitStatePo);
			unitLogDao.save(transform(unitStatePo));
		}
	}

	@Transactional
	public void runnable(StashUnit stashUnit) throws BrokerException {
		update(stashUnit, UnitStateEnum.RUNNABLE, "准备执行任务");
	}

	@Transactional
	public void running(StashUnit stashUnit) throws BrokerException {
		update(stashUnit, UnitStateEnum.RUNNING, "开始执行任务");
	}
	
	@Transactional
	public void fail(StashUnit stashUnit) throws BrokerException {
		update(stashUnit, UnitStateEnum.FAIL, "任务异常");
	}
	
	public void over(StashUnit stashUnit){
		unitStateDao.updateIsOver(stashUnit.getUnitCode(), stashUnit.getBatchNo(), "0");
		//over(stashUnit.getUnitProcId());
	}
	
	public void over(String unitProcId){
		unitStateDao.updateIsOver(unitProcId, "0");
	}


	@Transactional
	public void update(StashUnit stashUnit, UnitStateEnum state, String message) throws BrokerException {
		DataStashUnitStateLogPo unitStatePo = buildStatePo(stashUnit, state, message);
		unitStateDao.save(unitStatePo);
		flowlog(unitStatePo); 
	}

	@Transactional
	public void flowlog(StashUnit stashUnit, UnitStateEnum state) throws BrokerException {
		flowlog(stashUnit, state, null);
	}
	
	@Transactional
	public void flowlog(StashUnit stashUnit, UnitStateEnum state, String message) throws BrokerException {
		DataStashUnitStateLogPo unitStatePo = buildStatePo(stashUnit, state, message);
		unitLogDao.save(transform(unitStatePo));
	}
	@Transactional
	public void flowlog(DataStashUnitStateLogPo unitStatePo) throws BrokerException {
		unitLogDao.save(transform(unitStatePo));
	}

	private DataStashUnitStateLogPo buildStatePo(StashUnit stashUnit, UnitStateEnum state, String message)
			throws BrokerException {
		String unitProcId = stashUnit.getUnitProcId();
		DataStashUnitStateLogPo unitStatePo = unitStateDao.findOne(unitProcId);
		if (unitStatePo == null) {
			// TODO 报错，订单号不存在
			throw new BrokerException(ErrorCodeEnum.UnitProcIdNull, "订单号：" + unitProcId);
		}
		if(Strings.isNullOrEmpty(message)){
			unitStatePo.setMessage(state.label());
		}else{
			unitStatePo.setMessage(message);
		}
		
		unitStatePo.setState(state.value()); 
		unitStatePo.setLastupd(new Date());
		
		if (UnitStateEnum.RUNNING == state) {
			unitStatePo.setStartDt(GregorianCalendar.getInstance().getTime());
		} else if (UnitStateEnum.SUCESS == state) {
			unitStatePo.setCompleteDt(GregorianCalendar.getInstance().getTime());
		}
		return unitStatePo;
	}

	private DataStashUnitEventLogPo transform(DataStashUnitStateLogPo unitStatePo) {
		DataStashUnitEventLogPo logPo = BeanConvertUtils.copyBean(unitStatePo, DataStashUnitEventLogPo.class);
		logPo.setCreateDt(new Date());
		return logPo;
	}

}
